Skip to content

07 绕不过的坎儿 - VIM 文本编辑器

为什么要学 Vi/VIM

  • Linux 系统一切皆文件,文件编辑必不可少
  • Vi 是大多数发行版系统自带的文本编辑器,在任何场景下都可以使用
    • 无网络连接->无法远程登录
    • 无桌面系统->无法使用鼠标
    • 磁盘容量小->无法安装其他编辑器

Vi

  • 历史Vi 是 Visual Interface 的缩写,最初由 Bill Joy 在 1976 年为 BSD Unix 编写。
  • 功能Vi 是一个模式化的文本编辑器,它有三种基本模式:命令模式(Command mode)、插入模式(Insert mode)和末行模式(Last line mode)。
  • 特性Vi 的功能比较基础,适合进行快速的文本编辑任务。
  • 可用性:因为 Vi 是 Unix 系统的一部分,所以几乎所有的 Unix 和 Linux 发行版都会预装 Vi
  • 扩展性Vi 本身不支持插件。

VIM

  • 历史VIMvi IMproved 的缩写,由 Bram Moolenaar 在 1991 年基于 vi 开发。
  • 功能VIM 不仅包含了 vi 的所有功能,还增加了许多新特性,如多级撤销、语法高亮、命令行历史、在线帮助、文件名补全、块操作等。
  • 特性VIM 非常强大,支持多种编程语言的语法高亮和代码折叠,还有大量的插件可以增强其功能。
  • 可用性:虽然 VIM 不是所有 Unix 和 Linux 发行版的默认编辑器,但它通常可以通过包管理器轻松安装。
  • 扩展性VIM 支持插件,这使得它的功能可以通过社区开发的插件极大地扩展。

Vi 和 VIM 的区别

  • 部分发行版预安装 Vi,但是未安装 VIM
  • VIMVi 的升级版,两者基础指令无差别区别

功能和扩展性

  • Vi 是最初的版本,是 Unix 系统中的一个标准编辑器。它比较简单,功能有限,主要用于基本的文本编辑任务。
  • VIMVi 的增强版,它保留了 Vi 的所有功能,并增加了大量新功能和改进。VIM 支持语法高亮、多级撤销、多窗口编辑、代码折叠、插件支持等特性,使得它更适合于复杂的开发和编辑任务。

用户界面

  • Vi 和 VIM 在基本操作上非常相似,都是基于命令行界面的编辑器。它们没有图形用户界面(GUI),而是通过键盘命令来进行操作。
  • VIM 相对于 Vi 在用户体验上有一些改进,例如更友好的错误提示、更多的定制选项和键绑定。

兼容性

  • VIM 可以说是 Vi 的超集,几乎可以完全替代 Vi。VIM 保留了 Vi 的所有基本命令和操作方式,同时增加了许多新功能,因此在兼容性上,几乎所有 Vi 能够处理的任务,VIM 都可以胜任。

发展和社区

  • Vi是由 Bill Joy 在 1976 年开发的,它作为 Unix 系统的一部分,因其简洁和高效而广受欢迎。
  • VIM则由 Bram Moolenaar 在 1991 年开发,他增加了大量新特性,并积极维护和更新 VIM,使其成为当今最流行的文本编辑器之一。VIM 有一个活跃的社区支持和大量的插件生态系统。

VIM 的三种模式

  • 命令模式(Command mode):控制光标移动,可对文本进行复制、粘贴、删除和查找等工作。
  • 输入模式(Insert mode):正常的文本录入。
  • 末行模式(Last line mode):保存或退出文档,以及设置编辑环境。

VIM 编辑器模式的切换方法

图片源自:第 4 章 VIM 编辑器与 Shell 命令脚本 | 《Linux 就该这么学》

  • 在每次运行 VIM 编辑器时(执行 vim [file] 命令后),默认进入命令模式,此时需要先切换到输入模式后再进行文档编写工作。
  • 而每次在编写完文档后需要先返回命令模式,然后再进入末行模式,执行文档的保存或退出操作。
  • 在 VIM 中,无法直接从输入模式切换到末行模式。

命令模式

  • 命令模式是 VIM 的默认模式,当你启动 VIM 或者从其他模式(如插入模式)退出时,编辑器会进入命令模式。
  • 在命令模式中,用户可以使用各种键盘命令来操作文本,如导航、文本操作、剪切、复制、粘贴、查找和替换等。
    • 常用的光标移动命令包括:h/j/k/l(分别表示向左、向下、向上和向右移动光标)、w/b(分别表示移动到下一个单词的开头和上一个单词的开头)、e(移动到当前单词的末尾)等。
    • 常用的文本编辑命令包括:dd(删除光标所在行)、5dd(删除从光标处开始的 5 行)、yy(复制光标所在行)、5yy(复制从光标处开始的 5 行)、p(粘贴之前复制的文本)等。

进入和退出命令模式

  • 进入命令模式:启动 VIM 时默认进入命令模式。如果当前在其他模式(如插入模式),按 Esc 键返回命令模式。
  • 退出命令模式:在命令模式中,用户也可以通过输入特定的命令来切换到其他模式。
    • 输入 a/i/o 键切换到输入模式。
    • 输入 : 键切换到末行模式。

命令模式常用命令

命令作用
dd删除(剪切)光标所在整行
5dd删除(剪切)从光标处开始的 5 行
dw删除(剪切)光标所在位置到单词末尾的字符
x删除(剪切)光标所在位置的字符
u撤销上一步的操作
y复制选中内容
yy复制光标所在整行
5yy复制从光标处开始的 5 行
n显示搜索命令定位到的下一个字符串
N显示搜索命令定位到的上一个字符串
u撤销上一步的操作
p将之前删除(dd)或复制(yy)过的数据粘贴到光标后面
光标移动
命令作用
h/l向左/向右移动一个字符
j/k向下/向上移动一行
w/b(word)移动到下一个/上一个单词的开头
e移动到当前单词的末尾
W/BEw/be类似,但它们以空白字符作为单词的分隔符
0/$(Home/End)移动到行首/行尾
^移动到行首的第一个非空白字符
gg/G跳转到文件的第一行/最后一行
nG跳转到第 n 行
H/M/L移动到屏幕的顶部/中间/底部
文本修改
命令作用
x/X删除光标下的字符/光标前的字符
d(delete)开始删除(剪切)操作,通常与移动命令结合使用,例如 d2w 删除两个单词,dd/D 删除一行,d$ 删除到行尾,2dd 删除从光标处开始的 2 行
c(copy)开始修改操作,与 d 类似,但会在删除后进入插入模式,例如 c2w 修改两个单词,cc/C 修改一行
s(search)替换光标下的字符,并进入插入模式
S替换光标所在的整行,并进入插入模式
r(replace)替换光标下的字符,不进入插入模式
R进入替换模式,可以连续替换多个字符
y(yank)开始复制操作(复制到文件缓冲区),通常与移动命令结合使用,例如 yw 复制一个单词,yy/Y 复制一行,y$ 复制到行尾,2yy 复制从光标处开始的 2 行
p/P(paste)在光标后/光标前粘贴复制或删除的内容
撤销与重做
命令作用
u(undo)撤销最近的更改
Ctrl + r(redo)重做之前的撤销
搜索与替换
命令作用
/pattern在文档中向下搜索匹配的文本
?pattern在文档中向上搜索匹配的文本
n跳转到下一个匹配项
N跳转到上一个匹配项
:%s/old/new/g在整个文档中替换所有出现的 oldnew
其他操作
命令作用
.重复上一次的修改操作
>增加缩进
<减少缩进
zf创建折叠
zo打开折叠
zc关闭折叠

块编辑

命令作用
v进入字符可视模式,可以移动光标选择文本
V进入行可视模式,可以移动光标选择行
Ctrl + v进入块可视模式,可以移动光标选择矩形块
I在选中的每一行开始插入模式
A在选中的每一行的末尾插入模式
d删除选中的文本
c修改选中的文本
y复制选中的文本
>增加选中的每一行的缩进
<减少选中的每一行的缩进
=自动对齐选中的每一行
:noh取消高亮显示的搜索结果
  • 添加注释:先按下 Ctrl + v 进入块可视模式,然后使用上下箭头键选择要添加注释的行,最后按下 I 进入插入模式,输入 //,然后按下 Esc 键退出插入模式,注释就会被添加到选中的每一行前面。
  • 删除注释:先按下 Ctrl + v 进入块可视模式,然后使用上下箭头键选择要删除注释的行,最后按下 d 删除选中的文本,注释就会被删除。

插入模式

插入模式(Insert Mode)是一个允许你输入和编辑文本的模式。这是与命令模式(Normal Mode)最直接相对的模式,因为在插入模式中,你可以像在普通文本编辑器中那样输入字符。

命令作用
i(insert)在光标前插入文本
a(append)在光标后插入文本
o(open a new line below)在光标下一行插入文本
I在当前行首插入文本
A在当前行尾插入文本
O(open a new line above)在光标上一行插入文本
gi回到上一次离开插入模式的位置并进入插入模式
gI在当前行的开头插入文本,忽略缩进
命令说明
iIi是从光标所在位置开始输入,I是光标所在行第一个非空白字符开始输入
aAa是从光标所在的下一个字符开始输入,A是从光标所在行的最后一个字符开始输入
oOo是从光标所在行的下一行新的一行开始输入,O是从光标所在行的上一行新的一行开始输入
rRr是取代光标所在的字符一次,R是依次取代光标所在字符

插入模式的基本操作

进入插入模式后,可以进行以下操作:

  • 输入字符:直接输入文本字符。
  • 输入特殊字符:
    • <Ctrl-V> 后跟一个字符:插入该字符的字面值。
    • <Ctrl-R> 后跟寄存器名称:插入寄存器中的内容。
    • <Ctrl-O> 后跟命令模式命令:暂时回到命令模式执行一个命令,然后返回插入模式。

在插入模式中的光标移动

在插入模式中,常规的光标移动方式(如 h, j, k, l)将插入这些字符,而不是移动光标。然而,你可以使用以下组合键来移动光标:

KEY作用
<Ctrl-A>光标移动到行首
<Ctrl-E>光标移动到行尾
<Ctrl-F>光标向前移动一个字符
<Ctrl-B>光标向后移动一个字符
<Ctrl-N>光标向下移动一行
<Ctrl-P>光标向上移动一行
<Ctrl-D>光标向下移动半页
<Ctrl-U>光标向上移动半页
  • <Ctrl-H>:删除光标前的一个字符(同退格键)。
  • <Ctrl-W>:删除光标前的一个单词。
  • <Ctrl-U>:删除光标前的整行。
  • <Ctrl-D>:减少自动缩进。
  • <Ctrl-T>:增加自动缩进。
  • <Left>:左移光标。
  • <Right>:右移光标。
  • <Up>:上移光标。
  • <Down>:下移光标。

退出插入模式的方法

  • Esc:退出插入模式,回到命令模式。
  • <Ctrl-[>:功能与 Esc 相同,退出插入模式。
  • <Ctrl-C>:功能与 Esc 相同,退出插入模式。

使用插入模式的一些技巧

  • 自动完成:在插入模式中输入部分单词后,按 <Ctrl-N><Ctrl-P> 进行自动补全。
  • 多行插入:在命令模式下,选择多行(例如 V 然后移动光标选择多行),按 I 进入插入模式并输入内容,然后按 Esc,输入的内容将插入到每一行的开头。
  • 快速注释:在命令模式下,选择多行并输入 :,然后输入 '<,'>s/^/#/ 将在每行开头插入 #,使其变成注释。

插入模式中的插入命令

在插入模式中,有许多有用的命令可以帮助你更高效地编辑文本:

  • <Ctrl-E>:将插入点向下移动一行,但不离开插入模式。
  • <Ctrl-Y>:将插入点向上移动一行,但不离开插入模式。
  • <Ctrl-N>:自动完成单词(向下)。
  • <Ctrl-P>:自动完成单词(向上)。

插入模式中的高级操作

  • 录制和使用宏:在命令模式下按 q 然后选择一个寄存器(如 a),进入插入模式进行操作,按 q 结束录制。然后在命令模式下按 @a 可以重复执行该宏。
  • 粘贴模式:有时你需要从外部粘贴大量文本到 VIM 中,可以使用 :set paste 进入粘贴模式,然后按 i 进入插入模式并粘贴。结束后使用 :set nopaste 返回正常模式。

末行模式

末行模式(也称为命令行模式或 Ex 模式)是一种强大的模式,用于执行各种命令,如文件保存、退出、查找和替换、设置选项等。进入末行模式后,您可以在 VIM 窗口底部的命令行输入命令。

进入末行模式

在命令模式(Normal Mode)下,按下 : 键即可进入末行模式。光标将移动到窗口底部的命令行,等待输入命令。末行模式通常通过 :, /? 等符号进入:

  • ::用于执行大多数 Ex 命令。
  • /:用于向前查找。
  • ?:用于向后查找。

退出末行模式

按下 Esc 键可以退出末行模式并返回命令模式。

末行模式常用命令

命令作用
:w保存
:q退出
:q!强制退出(放弃对文档的修改内容)
:wq!强制保存退出
:set nu显示行号
:set nonu不显示行号
:命令执行该命令
:整数跳转到该行
:s/one/two将当前光标所在行的第一个one替换成two
:s/one/two/g将当前光标所在行的所有one替换成two
:%s/one/two/g将全文中的所有one替换成two
?字符串在文本中从下至上搜索该字符串
/字符串在文本中从上至下搜索该字符串
文件操作
命令作用
:w保存当前文件
:w!强制保存当前文件,即使文件权限不允许写入
:w filename将当前文件另存为指定的文件名
:q退出 VIM(如果有未保存的更改,将无法退出)
:wq / :x / ZZ保存当前文件并退出 VIM
:q! / ZQ不保存任何更改,强制退出 VIM
:e filename打开指定的文件,如果当前文件有更改则提示保存
:n打开下一个文件(在 VIM 中使用多个文件缓冲区时)
:prev / :N打开上一个文件(在 VIM 中使用多个文件缓冲区时)
:r filename将指定文件的内容读入当前文件,插入到光标所在位置
编辑操作
命令作用
:d删除当前行
:d {range}删除指定范围内的行,例如 :d 3,5 删除第 3 行到第 5 行
:y复制当前行
:y {range}复制指定范围内的行,例如 :y 3,5 复制第 3 行到第 5 行
:p在当前行后粘贴复制或删除的内容
:m {line}移动当前行到指定的行号,例如 :m 10 将当前行移动到第 10 行之后
查找和替换
命令作用
/pattern在文件中向前搜索匹配的文本
?pattern在文件中向后搜索匹配的文本
:s/old/new将当前行中的第一个 old 字符串替换为 new 字符串
:s/old/new/g将当前行中的所有 old 字符串替换为 new 字符串
:%s/old/new/g将整个文件中的所有 old 字符串替换为 new 字符串
:%s/old/new/gc将整个文件中的所有 old 字符串替换为 new 字符串,并在每次替换前进行确认
行范围
  • .:表示当前行。
  • $:表示最后一行。
  • ^:表示第一行。
  • n:表示第 n 行。例如 :n 跳转到第 n 行。
  • .$^ 等符号可以组合使用,例如:
    • :.,$d:删除从当前行到最后一行的所有行。
    • :1,$y:复制整个文件的所有行。
    • :2,10d:删除文件第 2 - 10 行。
    • :.=~:显示当前行号

窗口操作

  • :split:sp:水平分割窗口。
  • :vsplit:vsp:垂直分割窗口。
  • :close:关闭当前窗口。
  • :only:关闭除当前窗口外的所有窗口。

设置选项

  • :set option:设置选项。例如,:set number 显示行号。

  • :set nooption:关闭选项。例如,:set nonumber 关闭行号。

  • :set option=value:设置选项的值。例如,:set tabstop=4 将 Tab 宽度设置为 4 个空格。

  • 常用设置选项

    • :set nu:set number:显示行号。
    • :set nonu:set nonumber:关闭行号。
    • :set hlsearch:开启搜索高亮。
    • :set nohlsearch:关闭搜索高亮。
    • :set ignorecase:搜索时忽略大小写。
    • :set noignorecase:搜索时区分大小写。
    • :set tabstop=4:设置 Tab 宽度为 4 个空格。
    • :set expandtab:将 Tab 替换为空格。
    • :set noexpandtab:使用实际的 Tab 字符。

自定义命令

可以使用 :command 自定义命令。例如:

bash
:command WQ wq

这样,可以使用 :WQ 代替 :wq

执行外部命令

  • :!command:执行外部 shell 命令。例如,:!ls 列出当前目录的文件。

末行模式的组合使用

可以将多个命令组合在一起使用,例如:

bash
:1,10s/old/new/g | w

这个命令将文件的第 1 行到第 10 行中的所有 old 替换为 new,然后保存文件。